package vh.sphynx.runtime.pattern;

import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import vh.sphynx.runtime.IndexedMemberProvider;
import vh.sphynx.runtime.NamedMemberProvider;
import vh.sphynx.util.PatternMismatchedException;
import vh.sphynx.util.ReflectionUtil;
import vh.sphynx.util.SphynxRuntimeUtil;

public class DataPartMatchInfo extends PatternMatchInfo implements IndexedMemberProvider, NamedMemberProvider {

	private Map<Object, Object> fields;
	private Matcher matcher;

	public DataPartMatchInfo() {

	}
	
	@Override
	public String toString() {
		return super.toString() + ", matcher=" + matcher != null ? matcher.toString() : "null";
	}
	
	@Override
	public void intialize() {
		super.intialize();
		
		String strPattern = context.getVariableValue("dataPattern", String.class);		
		int flag = getOption("flag", Pattern.MULTILINE);
		
		if (strPattern != null && strPattern.length() > 0)
			match(strPattern, flag, true);
		
		fields = context.getVariableValueWithDefault("groups", null);
	}

	
	public void match(String pattern, int flag, boolean updatePosition) {
		Pattern regex = SphynxRuntimeUtil.compilePattern(pattern, flag);
		matcher = regex.matcher(getLocalInput());
		if (!matcher.find())
			throw new PatternMismatchedException(context, null, String.format("Unable to match '%s'", pattern));
		
		if (updatePosition) {
			setEndLocation(matcher.end() + getBeginLocation());
			setBeginLocation(matcher.start() + getBeginLocation());
		}
	}
	
	@Override
	public Object getMember(String fieldname) {
		if (fields != null && fields.containsKey(fieldname)) {
			int idx = (Integer) fields.get(fieldname);
			if (idx >= 0)
				return getMember(idx);
		}
		return null;
	}
	
	@Override
	public Object getMember(Object...indecies) {
		if (indecies[0] instanceof Integer) {
			Integer idx = (Integer)indecies[0];
			return matcher.group(idx);
		}
		if (indecies[0] instanceof String)
			return getMember((String)indecies[0]);
		return null;
	}
	
	@Override
	public boolean isWritable() {
		return false;
	}
	
	@Override
	public boolean isInitialized() {
		return isMatched();
	}

	@Override
	public void setMember(String name, Object value) {
		throw new UnsupportedOperationException();
	}

	@Override
	public void setMember(Object value, Object... indecies) {
		throw new UnsupportedOperationException();
	}

	@Override
	public boolean hasMember(String name) {
		return fields != null && fields.containsKey(name);
	}

	@Override
	public boolean hasMember(Object... indecies) {
		return indecies.length == 1 && (
				(indecies[0] instanceof String) || ReflectionUtil.isIntegerNumber(indecies[0]));
	}
}
